/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "iot_cloud.h"
#include "iot_profile.h"
#include "iot_boardled.h"
#include "iot_boardbutton.h"
#include "iot_nfc.h"
#include "iot_wifi.h"
#include "iot_netcfg.h"
#include "iot_sntp.h"
#include "ohos_init.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <cmsis_os2.h>
#include <stdbool.h>
#include "kv_store.h"
#include "iot_schedule.h"
#include "iot_demo_def.h"
#include "rice.h"
#include "hi_reset.h"
#include "network_config_service.h"
#include "iot_netcfg_nan.h"

#define    SID_KEY        "ssid"
#define    PWD_KEY        "password"

#define    SOFTAP_NAME    "teamX-Watering01"

// 默认参数，必须修改为真实参数
#define CONFIG_CLOUD_DEFAULT_SERVERIP "121.36.42.100"    // 将其替换为 iotplatform 服务器 ip
#define CONFIG_CLOUD_DEFAULT_SERVERPORT "1883"           // 将其替换为 iotplatform 服务器端口
#define CONFIG_SENSOR_SAMPLE_CYCLE 10000                  // 单位：毫秒
#define CONFIG_TASK_DEFAULT_STACKSIZE 0x1000             // 单位：字节
#define CONFIG_TASK_DEFAULT_PRIOR 20                     // 默认任务优先级
#define CONFIG_TASK_MAIN_STACKSIZE 0x4000                // 主任务堆栈大小必须最大
#define CONFIG_TASK_MAIN_PRIOR 25                        // 默认任务优先级
#define CONFIG_LOCAL_TIMEZONE            8
#define CONFIG_LED_DUTYCYCLEDEFAULT      20
#define CONFIG_LED_DUTYMAXMUN            99
#define CONFIG_LED_DUTYMINIMUM           1
#define CONFIG_FLASHLED_FRENETCONFIG     8
#define CONFIG_FLASHLED_FREWIFI          4
#define CONFIG_FLASHLED_FRECLOUD         1
#define CONFIG_FLASHLED_WORKSWELL        0.1
#define MAIN_TASK_DELAY_TICKS            100

typedef struct {
    int mainFlowerStatus;
    int curDay;
    int curSecondsInDay;
    bool lightManual;

    osTimerId_t timeID;
    int executeTime;
    int timerFlag;

    osEventFlagsId_t sensorTaskEvent;
} ApplicationController;
static ApplicationController g_appController;

#define CN_FLOWER_EVENT_SETSTATUS  (1<<0)
#define CN_LAMP_EVENT_ALL   (CN_FLOWER_EVENT_SETSTATUS)

//更新实时时钟
static void RtcTimeUpdate(void)
{
    
    extern int SntpGetRtcTime(int localTimeZone, struct tm *rtcTime);
    struct tm rtcTime;
    SntpGetRtcTime(CONFIG_LOCAL_TIMEZONE,&rtcTime);

    RaiseLog(LOG_LEVEL_INFO, "Year:%d Month:%d Mday:%d Wday:%d Hour:%d Min:%d Sec:%d",\
        rtcTime.tm_year + BASE_YEAR_OF_TIME_CALC, rtcTime.tm_mon + 1, rtcTime.tm_mday,\
        rtcTime.tm_wday, rtcTime.tm_hour, rtcTime.tm_min, rtcTime.tm_sec);

    if (rtcTime.tm_wday > 0) {
        g_appController.curDay = rtcTime.tm_wday - 1;
    } else {
        g_appController.curDay = EN_SUNDAY; 
    }

    g_appController.curSecondsInDay = rtcTime.tm_hour * CN_SECONDS_IN_HOUR +\
        rtcTime.tm_min * CN_SECONDS_IN_MINUTE + rtcTime.tm_sec + 8; // add 8 s offset
}

/**
  * @brief 将微秒转换为系统刻度
  * @param ms 表示要转换的毫秒数
  * @return 返回指定时间对应的刻度
 */
static uint32_t Time2Tick(uint32_t ms)
{
    uint64_t ret;
    ret = ((uint64_t)ms * osKernelGetTickFreq()) / CN_MINISECONDS_IN_SECOND;
    return (uint32_t)ret;
}

#define CN_REACTION_TIME_SECONDS   1
static void BoardLedButtonCallbackF1(char *arg)
{
    static uint32_t lastSec = 0;
    uint32_t curSec = 0;
    RaiseLog(LOG_LEVEL_INFO, "BUTTON PRESSED");

    curSec = g_appController.curSecondsInDay;
    if((curSec) < (lastSec + CN_REACTION_TIME_SECONDS)) {
        RaiseLog(LOG_LEVEL_WARN, "Frequecy Pressed Button");
        return;
    }
    lastSec = curSec;

    g_appController.lightManual = true;
    g_appController.mainFlowerStatus = CN_BOARD_SWITCH_ON;
    
    osEventFlagsSet(g_appController.sensorTaskEvent, CN_FLOWER_EVENT_SETSTATUS);
    return;
}

static void BoardLedButtonCallbackF2(char *arg)
{
    static uint32_t lastSec = 0;
    uint32_t curSec = 0;
    RaiseLog(LOG_LEVEL_INFO, "BUTTON PRESSED");

    curSec = g_appController.curSecondsInDay;
    if((curSec) < (lastSec + CN_REACTION_TIME_SECONDS)) {
        RaiseLog(LOG_LEVEL_WARN, "Frequecy Pressed Button");
        return;
    }
    lastSec = curSec;

    g_appController.lightManual = true;
    g_appController.mainFlowerStatus = CN_BOARD_SWITCH_OFF;
    osEventFlagsSet(g_appController.sensorTaskEvent, CN_FLOWER_EVENT_SETSTATUS);

    return;
}

/**
     传感器数据采集任务入口及主要流程如下：
  * 1、等待事件在指定时间触发
  * 2、收集传感器数据
  * 3、将采集到的数据上报到云平台
 */
static void DataCollectAndReport(const void *arg)
{
    (void)arg;

    //传感器任务事件
    uint32_t sensorTaskEvent;

    uint32_t waitTicks;

    //记录传感器数据
    int temperature = 0; 
    int humidity = 0;
    int moisture = 0;

    //等待时间
    waitTicks = Time2Tick(CONFIG_SENSOR_SAMPLE_CYCLE);

    while (1) {


        sensorTaskEvent = osEventFlagsWait(g_appController.sensorTaskEvent, CN_LAMP_EVENT_ALL, \
            osFlagsWaitAny, waitTicks);

        //当所有的条件满足时，启动电机，开始降温、除湿
        if (sensorTaskEvent & CN_FLOWER_EVENT_SETSTATUS) {
            RaiseLog(LOG_LEVEL_ERR, "FlowerSetMotorStatus %s! \n", g_appController.mainFlowerStatus ? "ON" : "OFF");
            
            //启动电机
            FlowerSetMotorStatus(g_appController.mainFlowerStatus);
        }

        //启动空气湿度检测
        if (FlowerGetAirStatus(&temperature, &humidity) != 0) {
            RaiseLog(LOG_LEVEL_ERR, "BOARD_GetAirStatus temperature && humidity  failed! \n");
        }

        //启动土壤湿度检测
        if (FlowerGetSoilStatus(&moisture) != 0) {
            RaiseLog(LOG_LEVEL_ERR, "BOARD_GetSoilStatus failed! \n");
        }

        //打包(temperature, humidity, moisture状态)成· prodfile
        IotProfile_Report(g_appController.mainFlowerStatus, temperature, humidity, moisture);
        RaiseLog(LOG_LEVEL_INFO, "Get the sensor Data-->temperature:%d humidity:%d moisture:%d, Motor status = %s\n",\
            temperature,humidity, moisture, g_appController.mainFlowerStatus ? "ON" : "OFF");
    }
    return;
}

static int UpdateShedule(CommandParamSetShedule *shedule)
{
      // 将一个时间表设置为当前工作日
    if (shedule->num == 1 && shedule->day[0] == 0) 
    {              
        shedule->day[0] = (g_appController.curDay + 1);
    }
    
    //日程选项
    switch (shedule->option) {
        case 'A':
        //添加日程
            IOT_ScheduleAdd(shedule->scheduleID, shedule->day, shedule->num, shedule->startHour * CN_SECONDS_IN_HOUR +\
                shedule->startMinute * CN_SECONDS_IN_MINUTE, shedule->duration, shedule->motorCmd.status, shedule->motorCmd.capacity);
            break;
        case 'U':
        //更新日程
            IOT_ScheduleUpdate(shedule->scheduleID, shedule->day, shedule->num, shedule->startHour * CN_SECONDS_IN_HOUR +\
                shedule->startMinute * CN_SECONDS_IN_MINUTE, shedule->duration, shedule->motorCmd.status, shedule->motorCmd.capacity);
            break;
        case 'D':
        //删除日程
            IOT_ScheduleDelete(shedule->scheduleID, shedule->day, shedule->num, shedule->startHour * CN_SECONDS_IN_HOUR +\
                shedule->startMinute * CN_SECONDS_IN_MINUTE, shedule->duration, shedule->motorCmd.status, shedule->motorCmd.capacity);
            break;
        //无所选日程执行以下
        default:
            RaiseLog(LOG_LEVEL_ERR, "the schedule has no such option!\n");
            break;
    }
    return 0;
}

#define TIMER_TICK_NUM  100
static void TimerHandle(void *ars)
{
    g_appController.curSecondsInDay++;

    if (g_appController.timerFlag) {
         if (g_appController.executeTime > 0) {
             g_appController.executeTime--;
         }
    }
}

//护花使者日程管理
static void FlowerShedule(void)
{
    //时间管理；启动与停止
    int startSecondInDay = 0;
    int endSecondInDay = 0;
 
    //定义设置主电机命令的参数 ：启动电机，停止电机
    CommandParamSetControlMotor motorStatus, lastMotorStatus;

    while(1) {
        osDelay(Time2Tick(CN_MINISECONDS_IN_SECOND));

        //在显示屏上上传的时间日期
        RaiseLog(LOG_LEVEL_INFO, "dayTime --> %02d:%02d:%02d \n", g_appController.curSecondsInDay / CN_SECONDS_IN_HOUR,\
            (g_appController.curSecondsInDay % CN_SECONDS_IN_HOUR) / CN_SECONDS_IN_MINUTE,\
            g_appController.curSecondsInDay % CN_SECONDS_IN_MINUTE);
 
        // 计算一天中的秒数
        if (g_appController.curSecondsInDay >= CN_SECONS_IN_DAY) {
            g_appController.curSecondsInDay = 0;
            g_appController.curDay++;
            g_appController.lightManual = false;   // 清除它
            if (g_appController.curDay >= EN_DAYALL) {
                g_appController.curDay = EN_MONDAY;
            }
            IOT_ScheduleSetUpdate(1);
        }

        // 检查时间表是否有更新
        if (IOT_ScheduleIsUpdate(g_appController.curDay, g_appController.curSecondsInDay)) {
            if (g_appController.timerFlag) {
                g_appController.executeTime = 0;
                g_appController.timerFlag = 0;
                if (g_appController.mainFlowerStatus == CN_BOARD_SWITCH_ON) {
                    g_appController.mainFlowerStatus = CN_BOARD_SWITCH_OFF;
                    osEventFlagsSet(g_appController.sensorTaskEvent, CN_FLOWER_EVENT_SETSTATUS);
                }
            }
            startSecondInDay = IOT_ScheduleGetStartTime();
            endSecondInDay = startSecondInDay + IOT_ScheduleGetDurationTime();
            IOT_ScheduleGetCommand(&(motorStatus.status), &(motorStatus.capacity));
        }

        if (g_appController.timerFlag == 0) {
            
            //显示日程的设置结果：启动时间、停止时间、中间时间的间隔
            RaiseLog(LOG_LEVEL_INFO, "start:%d end:%d cur:%d",
                startSecondInDay, endSecondInDay, g_appController.curSecondsInDay);

            if ((g_appController.curSecondsInDay  >= startSecondInDay) && \
                (g_appController.curSecondsInDay < endSecondInDay)) {
                lastMotorStatus.status = g_appController.mainFlowerStatus;
                g_appController.mainFlowerStatus = motorStatus.status;
                if (g_appController.mainFlowerStatus != lastMotorStatus.status) {
                    RaiseLog(LOG_LEVEL_INFO, "Triggering");
                    g_appController.mainFlowerStatus = CN_BOARD_SWITCH_ON;
                    osEventFlagsSet(g_appController.sensorTaskEvent, CN_FLOWER_EVENT_SETSTATUS);
                }
                g_appController.executeTime = endSecondInDay - g_appController.curSecondsInDay;
                g_appController.timerFlag = 1;
            }
        } 
        else 
        {
            if (g_appController.executeTime == 0) 
            {
                if (g_appController.mainFlowerStatus != CN_BOARD_SWITCH_OFF) 
                {
                    g_appController.mainFlowerStatus = CN_BOARD_SWITCH_OFF;
                    osEventFlagsSet(g_appController.sensorTaskEvent, CN_FLOWER_EVENT_SETSTATUS);
                }

                IOT_ScheduleSetUpdate(1);
                startSecondInDay = 0;
                endSecondInDay = 0;
                memset(&lastMotorStatus, 0x00, sizeof(lastMotorStatus));
                g_appController.timerFlag = 0;
            }
        }
    }

    return;
}

/**
 * @brief 回调函数，用于处理云平台下发的命令
  * @param command 表示云平台下发的命令
  * @param value 表示命令对应的参数
  * @return 返回 0 成功而 -1 失败
 */
int IotProfile_CommandCallback(int command, void *buf)
{
    CommandParamSetShedule setSheduleParam;
    CommandParamSetControlMotor setControlMotorParam;

    CLOUD_CommandType cmd = (CLOUD_CommandType)command;

    /** 
      * 这里我们只处理云平台下发的控制电机的命令，
      * 值应为 CN_BOARD_SWITCH_ON 或 CN_BOARD_SWITCH_OFF 
     */
    if (cmd == CLOUD_COMMAND_CONTROLMOTOR)
    {
        setControlMotorParam = *(CommandParamSetControlMotor *)buf;
        
        if (g_appController.mainFlowerStatus != setControlMotorParam.status) 
        {
            g_appController.mainFlowerStatus = setControlMotorParam.status;
            g_appController.lightManual = true;
            if (g_appController.mainFlowerStatus == CN_BOARD_SWITCH_ON)
            {
                g_appController.executeTime = setControlMotorParam.capacity / 10;
                g_appController.timerFlag = 1;
            }
            RaiseLog(LOG_LEVEL_INFO, "setControlMotor:%d\r\n", setControlMotorParam.status);
            osEventFlagsSet(g_appController.sensorTaskEvent, CN_FLOWER_EVENT_SETSTATUS);
        }
        
        return 0;

    } 
    else if (cmd == CLOUD_COMMAND_SETSHEDULE) 
    {
        setSheduleParam = *(CommandParamSetShedule *)buf;
        RaiseLog(LOG_LEVEL_INFO, "setshedule:day:%d hour:%d minute:%d duration:%d \r\n", \
            setSheduleParam.day,setSheduleParam.startHour,setSheduleParam.startMinute, setSheduleParam.duration);
        return UpdateShedule(&setSheduleParam);
    }

    return -1;
}

static int IotWifiInfo_get(char *ssid, int id_size, char *pwd, int pd_size)
{
    int retval = UtilsGetValue(SID_KEY, ssid, id_size);
    if (retval <= 0) {
        RaiseLog(LOG_LEVEL_ERR, "no such ssid stored! \n");
        return 0;
    }
    //修改过的区域
    RaiseLog(LOG_LEVEL_INFO, " such ssid stored! \n");


    if ( UtilsGetValue(PWD_KEY, pwd, pd_size) < 0) 
    {
        RaiseLog(LOG_LEVEL_INFO, "ssid(%s) no password stored! \n", ssid);
    } 
    else 
    {
        RaiseLog(LOG_LEVEL_INFO, "ssid : %s, pwd : %s! \n", ssid, pwd);
    }

    return 1;
}

static void IotWifiInfo_set(char *ssid, char *pwd)
{
    if (UtilsSetValue(SID_KEY, ssid) != 0) 
    {
        RaiseLog(LOG_LEVEL_ERR, "store ssid failed! \n");
        return;
    }
    //修改过的
    RaiseLog(LOG_LEVEL_ERR, "LOG_LEVEL_INFOstore ssid success! \n");

    if (UtilsSetValue(PWD_KEY, pwd) != 0) 
    {
        RaiseLog(LOG_LEVEL_ERR, "store password failed! \n");
        UtilsDeleteValue(SID_KEY);
        return;
    }
    RaiseLog(LOG_LEVEL_INFO, "store password success! \n");
}

/**
    IoTMain任务入口及主要流程如下：
  * 1、初始化必要的硬件并从NFC中获取相应的信息
  * 2、连接wifi
  * 3、连接华为云平台
  * 4、创建传感器采集任务
 */

static void IotMainTaskEntry(const void *arg)
{
    
    osThreadAttr_t attr;
    NfcInfo nfcInfo;
    (void)arg;
    //存放通过NFC读取的      WIFI名称ssid    和  WIFI密码pwd
    char ssid[BUFF_SIZE] = {0};
    char pwd[BUFF_SIZE] = {0};

    int ret = 0;

    //设备初始化
    BOARD_InitPwmLed();
    FlowerInit();
    BOARD_InitWifi();
    IOT_ScheduleInit();

    //检测F2按键的状态(网络配置按键)
    ret = Board_IsButtonPressedF2();
    osDelay(MAIN_TASK_DELAY_TICKS);
    Board_InitButtonF1(BoardLedButtonCallbackF1, NULL);
    Board_InitButtonF2(BoardLedButtonCallbackF2, NULL);

    // LED闪烁频率设置  状态显示
    LedFlashFrequencySet(CONFIG_FLASHLED_FRENETCONFIG);

    
    //设备接入华为云的  设备ID 和 设备识别码
    nfcInfo.deviceID = "621068a3de9933029be8e65b_RiceCooker";
    nfcInfo.devicePWD = "12345678";

    //判断按键按下后，启动无感配网相关服务，用来获取相关配网账号信息
    if (ret) 
    {
        RaiseLog(LOG_LEVEL_INFO, "Netconfig Button has pressed! \n");

        //BOARD_NAN_NetCfgStartConfig();    无感配网相关服务，用来获取相关配网账号信息
        if (BOARD_NAN_NetCfgStartConfig(SOFTAP_NAME, ssid, sizeof(ssid), pwd, sizeof(pwd)) < 0) 
        {
            RaiseLog(LOG_LEVEL_ERR, "BOARD_NetCfgStartConfig failed! \n");
            return;
        } 
        else 
        {
            ret = AFTER_NETCFG_ACTION;
            //修改过的
            RaiseLog(LOG_LEVEL_INFO, "BOARD_NetCfgStartConfig success! \n");

        }
    }
    //如果按键没有按下，则读取已保存的热点ssid，pwd
    else 
    {
        ret = IotWifiInfo_get(ssid, sizeof(ssid), pwd, sizeof(pwd));
        if (ret == 0)
         {
            if (BOARD_NAN_NetCfgStartConfig(SOFTAP_NAME, ssid, sizeof(ssid), pwd, sizeof(pwd)) < 0)
            {
                RaiseLog(LOG_LEVEL_ERR, "BOARD_NetCfgStartConfig failed! \n");
                return;
            }
            else 
            {
                ret = AFTER_NETCFG_ACTION;
                //修改过的
                RaiseLog(LOG_LEVEL_INFO, "BOARD_NetCfgStartConfig success! \n");
            }
        } 
    }
    
    //减低LED闪烁频率，表示进入下一阶段----具体的联网操作
    LedFlashFrequencySet(CONFIG_FLASHLED_FREWIFI);

    //获取到WIFI信息后，开始连接WIFI网络
    if (BOARD_ConnectWifi(ssid, pwd) != 0) 
    {
        //网络连接失败则进行以下操作

        //串口显示连接失败信息
        RaiseLog(LOG_LEVEL_ERR, "BOARD_ConnectWifi failed! \n");

        //如果有上次连接设备信息，则进行重新连接设备
        if (ret == AFTER_NETCFG_ACTION) 
        {
            //发送配网信息无效给应用
            NotifyNetCfgResult(NETCFG_DEV_INFO_INVALID);
        }
        
        //系统重置开始
        hi_hard_reboot(HI_SYS_REBOOT_CAUSE_CMD);

        return;
    }

    if (ret == AFTER_NETCFG_ACTION) {
        
        //显示设备连接上一次设备成功
        RaiseLog(LOG_LEVEL_DEBUG, "Connect wifi success ! \n");

        //网络连接成功，发送配网成功消息给应用
        NotifyNetCfgResult(NETCFG_OK);

        osDelay(MAIN_TASK_DELAY_TICKS);

        // 停止网络配置
        RaiseLog(LOG_LEVEL_DEBUG, "StopNetCfg wifi success ! \n");        
        StopNetCfg();

        //将热点信息保存到文件系统中
        IotWifiInfo_set(ssid, pwd);
    }
    // 更新 RTC 时间并连接云端，LED 闪烁再降一级别
    LedFlashFrequencySet(CONFIG_FLASHLED_FRECLOUD);

    //实时时钟更新
    RtcTimeUpdate();

    //创建云通信数据接收消息队列，创建云通信处理任务
    //处理发送消息或接收消息
    if (CLOUD_Init() != 0) {
        return;
    }

    //需要提供设备ID、密码、服务器IP地址、服务器端口
    if (CLOUD_Connect(nfcInfo.deviceID, nfcInfo.devicePWD, \
        CONFIG_CLOUD_DEFAULT_SERVERIP, CONFIG_CLOUD_DEFAULT_SERVERPORT) != 0) {
        return;
    }

    //LED闪烁降至0.1
    LedFlashFrequencySet(CONFIG_FLASHLED_WORKSWELL);
    
    //创建一个定时器名为g_appController
    g_appController.timeID = osTimerNew(&TimerHandle, osTimerPeriodic, NULL, NULL);
    /*
    
	timer_id	    osTimerCreate获取的定时器 ID 。
	TIMER_TICK_NUM	定时器的延时值。
    */
    //定时器启动
    osTimerStart(g_appController.timeID, TIMER_TICK_NUM);

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = CONFIG_TASK_DEFAULT_STACKSIZE;
    attr.priority = CONFIG_TASK_DEFAULT_PRIOR;

    //创建一个名称为 "DataCollectAndReport" 的事件
    attr.name = "DataCollectAndReport";
    if (osThreadNew((osThreadFunc_t)DataCollectAndReport, NULL, (const osThreadAttr_t *)&attr) == NULL) {
        return;
    }

    //创建一个名称为 "FlowerShedule" 的事件
    attr.name = "FlowerShedule";
    if (osThreadNew((osThreadFunc_t)FlowerShedule, NULL, (const osThreadAttr_t *)&attr) == NULL) {
        return;
    }
    return;
}

/**
 * @brief IoT-Flower项目的IoT主入口
 */

static void IotMainEntry(void)
{
    osThreadAttr_t attr;
    RaiseLog(LOG_LEVEL_INFO, "DATA:%s Time:%s \r\n",__FUNCTION__, __DATE__, __TIME__);
    memset(&g_appController, 0x00, sizeof(g_appController));
    
    g_appController.sensorTaskEvent = osEventFlagsNew(NULL);
    if ( g_appController.sensorTaskEvent == NULL) {
        return;
    }
    
    // 创建 IoT 主任务
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = CONFIG_TASK_MAIN_STACKSIZE;
    attr.priority = CONFIG_TASK_MAIN_PRIOR;

    //创建一个名称为 "IoTMain" 的事件，优先级为25
    attr.name = "IoTMain";
    (void) osThreadNew((osThreadFunc_t)IotMainTaskEntry, NULL, (const osThreadAttr_t *)&attr);

    return;
}
//将 IotMainEntry 函数添加到系统启动过程
APP_FEATURE_INIT(IotMainEntry);
